{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  ARIMA fault detection algorithm\n",
    "\n",
    "Pipeline for the anomaly detection on the SKAB. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The idea behind this algorithm is to use ARIMA weights as features for the anomaly detection algorithm. Using discrete differences of weight coefficients for different heuristic methods for obtaining function, which characterized the state (anomaly, not anomaly) using a threshold. \n",
    "\n",
    "Links at [PyPi](https://pypi.org/project/arimafd/), [GitHub](https://github.com/waico/arimafd) and [paper](https://waico.ru)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'other'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-1-21d7b3180bfe>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'../utils'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mevaluating\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mevaluating_change_point\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mother\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMeshLoader\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'other'"
     ]
    }
   ],
   "source": [
    "# libraries importing\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import pickle\n",
    "\n",
    "\n",
    "# additional modules\n",
    "import sys\n",
    "sys.path.append('../utils')\n",
    "from evaluating import evaluating_change_point\n",
    "from other import MeshLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from numpy import linalg\n",
    "import pandas as pd\n",
    "from sympy import diff, symbols, sympify, Symbol, poly\n",
    "from sklearn.preprocessing import MinMaxScaler, StandardScaler\n",
    "from time import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data loading"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# benchmark files checking\n",
    "all_files=[]\n",
    "import os\n",
    "for root, dirs, files in os.walk(\"../data/\"):\n",
    "    for file in files:\n",
    "        if file.endswith(\".csv\"):\n",
    "             all_files.append(os.path.join(root, file))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# datasets with anomalies loading\n",
    "list_of_df = [pd.read_csv(file, \n",
    "                          sep=';', \n",
    "                          index_col='datetime', \n",
    "                          parse_dates=True) for file in all_files if 'anomaly-free' not in file]\n",
    "# anomaly-free df loading\n",
    "anomaly_free_df = pd.read_csv([file for file in all_files if 'anomaly-free' in file][0], \n",
    "                            sep=';', \n",
    "                            index_col='datetime', \n",
    "                            parse_dates=True)\n",
    "true_cp = [df.changepoint for df in list_of_df]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data description and visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# dataset characteristics printing\n",
    "print(f'A number of datasets in the SkAB v1.0: {len(list_of_df)}\\n')\n",
    "print(f'Shape of the random dataset: {list_of_df[0].shape}\\n')\n",
    "n_cp = sum([len(df[df.changepoint==1.]) for df in list_of_df])\n",
    "n_outlier = sum([len(df[df.anomaly==1.]) for df in list_of_df])\n",
    "print(f'A number of changepoints in the SkAB v1.0: {n_cp}\\n')\n",
    "print(f'A number of outliers in the SkAB v1.0: {n_outlier}\\n')\n",
    "print(f'Head of the random dataset:')\n",
    "display(list_of_df[0].head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# random dataset visualizing\n",
    "list_of_df[0].plot(figsize=(12,6))\n",
    "plt.xlabel('Time')\n",
    "plt.ylabel('Value')\n",
    "plt.title('Signals')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# plotting the labels both for outlier and changepoint detection problems\n",
    "list_of_df[0].anomaly.plot(figsize=(12,3))\n",
    "list_of_df[0].changepoint.plot()\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Method applying"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from arimafd import *\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if os.path.exists(r'tensors.pickle'):\n",
    "    with open(r'tensors.pickle', 'rb') as f:\n",
    "        tensors = pickle.load(f)\n",
    "else:\n",
    "    tensors = []\n",
    "    for df in list_of_df:\n",
    "        a = anomaly_detection(df.iloc[:,:-2])\n",
    "        tensors.append(a.generate_tensor(ar_order=100))\n",
    "    with open(r'tensors.pickle', 'wb') as handle:\n",
    "        pickle.dump(tensors, handle, protocol=pickle.HIGHEST_PROTOCOL)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metrics = range(1,6)\n",
    "windows= [20,50,100,150]\n",
    "window_insensitivitys = [20,50,100,150]\n",
    "history = []\n",
    "for No_metric,window,window_insensitivity in MeshLoader([metrics,windows,window_insensitivitys]):\n",
    "    print('XXX',No_metric,window,window_insensitivity)\n",
    "    predicted_cp=[]\n",
    "    predicted_cp1 = []\n",
    "    for i,df in enumerate(list_of_df):\n",
    "        acci = df.changepoint\n",
    "        a = anomaly_detection(df)\n",
    "        a.tensor = tensors[i]\n",
    "        a.proc_tensor(No_metric=No_metric, window=window, window_insensitivity=window_insensitivity)\n",
    "        predicted_cp.append(a.bin_metric)\n",
    "    nab = evaluating_change_point(true_cp, predicted_cp, metric='nab', numenta_time='30 sec')\n",
    "    history.append([No_metric, window, window_insensitivity, nab[0], nab[1], nab[2]])\n",
    "    print(history)\n",
    "    print()\n",
    "    print()\n",
    "history = pd.DataFrame(history, columns=['No_metric','window','window_insensitivity','Standart','LowFP','LowFN'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.gridspec as gridspec\n",
    "\n",
    "f = plt.figure(figsize=(16,4))\n",
    "grid = gridspec.GridSpec(1, len(metrics),wspace =0.7)\n",
    "for i in metrics:\n",
    "    globals()['ax'+str(i)] = f.add_subplot(grid[i-1])\n",
    "    history[history.No_metric==i].plot.scatter(x='window',y='window_insensitivity', c='Standart', colormap='viridis',ax=globals()['ax'+str(i)])\n",
    "    globals()['ax'+str(i)].set_title(f\"Metric {i}\")\n",
    "    \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "No_metric= 5\n",
    "window= 150\n",
    "window_insensitivity = 20\n",
    "\n",
    "predicted_cp=[]\n",
    "for i,df in enumerate(list_of_df):\n",
    "    acci = df.changepoint\n",
    "    a = anomaly_detection(df)\n",
    "    a.tensor = tensors[i]\n",
    "    a.proc_tensor(No_metric=No_metric,window=window, window_insensitivity=window_insensitivity)\n",
    "    predicted_cp.append(a.bin_metric)\n",
    "nab = evaluating_change_point(true_cp, predicted_cp, metric='nab', numenta_time='30 sec')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "add = evaluating_change_point(true_cp, predicted_cp, metric='average_delay', numenta_time='30 sec')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
